home *** CD-ROM | disk | FTP | other *** search
- #include "MusicClasses.h"
- #include <iostream.h>
-
- void GenerateHexFromLong(long initial, ofstream& outFile);
-
- Note Measure::getStackedNote(int n){
- Note retNote;
- if (numNotes < n) {
- retNote.pitch = -100;
- retNote.duration = 1;
- retNote.volume = 0x40;
- } else
- retNote = noteLine[numNotes - n];
-
- return retNote;
- }
-
- void Song::OutputToFile(ofstream& outFile) {
-
- outFile << "MThd"; //header information
- outFile.put(0x00);
- outFile.put(0x00);
- outFile.put(0x00);
- outFile.put(0x06);
-
- outFile.put(0x00);
- outFile.put(0x01);
- outFile.put(0x00);
- outFile.put(0x01);
- outFile.put(0x00);
- outFile.put(0x04);
-
-
- outFile << "MTrk"; //track information
-
- long initial = CountNumBytes() + 4;
- GenerateHexFromLong(initial, outFile); //length
-
- Unit* current = headPointer;
- while (current != nil) {
- current -> OutputToFile(outFile);
- current = current -> getNext();
- }
-
- outFile.put(0x00);
- outFile.put(0xFF);
- outFile.put(0x2F);
- outFile.put(0x00);
-
- }
-
- void Unit::OutputToFile(ofstream& outFile) {
- for (int i = 0; i < 12; i++)
- (mArray[i]).OutputToFile(outFile, i);
- }
-
- void Measure::OutputToFile(ofstream& outFile, int measureNum) {
- char chord[3];
-
- switch (measureNum) {
- case 8:
- chord[1] = 0x34;
- chord[2] = 0x3A;
- chord[3] = 0x3E;
- break;
- case 1: case 4: case 5: case 9:
- chord[1] = 0x32;
- chord[2] = 0x38;
- chord[3] = 0x3C;
- break;
- case 3:
- chord[1] = 0x33;
- chord[2] = 0x39;
- chord[3] = 0x3D;
- break;
- case 11:
- chord[1] = 0x34;
- chord[2] = 0x3A;
- chord[3] = 0x3F;
- break;
- default:
- chord[1] = 0x33;
- chord[2] = 0x39;
- chord[3] = 0x3E;
- break;
- }
-
-
- for (int i = 0; i < 3; i++) {
- outFile.put(0x00); //delta time is nothing
- outFile.put(0x90); //note on event--channel 0 (i.e. 1)
- outFile.put(chord[i]); //pitch plus F below middle C (in half steps)
- outFile.put(0x40); //normal accent
- }
-
- for (int i = 0; i < numNotes; i++)
- noteLine[i].OutputToFile(outFile);
-
- /* outFile.put(0x00); //stop! event
- outFile.put(0xF7);
- outFile.put(0x01);
- outFile.put(0xFC);
-
- outFile.put(0x10); //continue! event
- outFile.put(0xF7);
- outFile.put(0x01);
- outFile.put(0xFB);
- */
- for (int i = 0; i < 3; i++) {
- outFile.put(0x00); //duration of note in ticks (16ths for now)
- outFile.put(0x80); //note off event--channel 0 (i.e. 1)
- outFile.put(chord[i]); //pitch plus F below middle C (in half steps) minus octove
- outFile.put(0x40); //normal accent
- }
-
-
- }
-
- void Note::OutputToFile(ofstream& outFile) {
- if (pitch == -100) { //-100 means rest
- outFile.put(0x00); //stop event
- outFile.put(0xF7);
- outFile.put(0x01);
- outFile.put(0xFC);
-
- outFile.put(char(duration)); //continue event
- outFile.put(0xF7);
- outFile.put(0x01);
- outFile.put(0xFB);
- }
- else { //otherwise send note on event
- outFile.put(0x00); //delta time is nothing
- outFile.put(0x90); //note on event--channel 0 (i.e. 1)
- outFile.put((char)(0x35 + pitch)); //pitch plus F below middle C (in half steps)
- outFile.put(volume); //normal accent
-
- outFile.put(char(duration)); //duration of note in ticks (16ths for now)
- outFile.put(0x80); //note off event--channel 0 (i.e. 1)
- outFile.put((char)(0x35 + pitch)); //pitch plus F below middle C (in half steps) minus octove
- outFile.put(volume); //normal accent
- }
- }
-
- Song::Song()
- {
- headPointer = new Unit;
- }
-
- Song::Song(ifstream& fin)
- {
- Unit* curUnit;
- headPointer = new Unit(fin);
- headPointer->getNext() = new Unit(fin);
- curUnit = headPointer->getNext();
- curUnit->getNext() = new Unit(fin);
- curUnit = curUnit->getNext();
- curUnit->getNext() = new Unit(fin);
- curUnit = curUnit->getNext();
- curUnit->getNext() = new Unit(fin);
- curUnit = curUnit->getNext();
- curUnit->getNext() = new Unit(fin);
- curUnit = curUnit->getNext();
- }
-
- Unit::Unit(ifstream& fin) {
- nextUnit = nil;
-
- PitchLine* p1;
- SyncLine* s1;
-
- pList = nil;
- sList = nil;
-
- pList = new PitchLine(nil, fin);
- sList = new SyncLine(nil, pList, fin);
-
- p1 = pList;
- s1 = sList;
-
- for(short C = 1; C < 3; C++) {
- p1->getNext() = new PitchLine(nil, fin);
- s1->getNext() = new SyncLine(nil, pList, fin);
- p1 = p1->getNext(); //increment p1
- s1 = s1->getNext();
- }
-
- WriteMeasures(fin);
- }
-
-
- long Song::CountNumBytes() {
- Unit* curUnit = headPointer;
- long numBytes = 0;
-
- for(numBytes = 0; curUnit != nil; curUnit = curUnit->getNext())
- numBytes += curUnit->CountNumBytes();
-
- return numBytes;
-
- }
-
- long Unit::CountNumBytes() {
- short measure;
- long numBytes = 0;
-
- for (measure = 0; measure < 12; ++measure)
- numBytes += 8*mArray[measure].GetNumNotes();
-
- numBytes += 12 * 24; //chord bytes
- return numBytes;
- }
-
- int Measure::GetNumNotes() {
- return numNotes;
- }
-
- void GenerateHexFromLong(long initial, ofstream& outFile) {
- char zeroChar = 0x00;
- char holder[4];
-
- for (int i = 0; i < 4; i++) {
- holder[i] = initial | zeroChar;
- initial >>= 8;
- }
-
- for (int i = 0; i < 4; i++)
- outFile.put(holder[3 - i]);
- }
-
- Note::Note(short newPitch, long newDuration)
- : pitch(newPitch),
- duration(newDuration)
- {
- }
-
-
- int Measure::AddNote(Note newNote) { //adds new note at end of part of measure written so far
- noteLine[numNotes] = newNote;
- return ++numNotes; //prefix!!!
- }
-
- void Unit::WriteMeasures(ifstream& fin) {
- PitchLine* plTemp;
- SyncLine* slTemp;
- int beatCount; //16th note equivalents used so far this measure
- int measureCount = 0;
- int measureCountInPitchLine = 0;
- char random;
- Note keyNote;
-
- plTemp = pList;
- slTemp = sList;
-
- while (plTemp != nil && slTemp != nil) {
- //pitch line loop:
- for (measureCountInPitchLine = 0; measureCountInPitchLine < 4; measureCountInPitchLine++) {
- //measure loop:
- for (beatCount = 0; beatCount < 16; /*++beatCount*/) {
- fin >> random;
- keyNote = PickNote(measureCount, plTemp, slTemp, beatCount, random);
- mArray[measureCount].AddNote(keyNote);
- beatCount += keyNote.duration;
- }
- ++measureCount;
- }
- plTemp = plTemp->getNext();
- slTemp = slTemp->getNext();
- }
-
- }
-
- long min(long a, long b) {
- return (a < b) ? a : b;
- }
-
-
- //Interesting functions begin here
-
-
- PitchLine::PitchLine(PitchLine* pitchLineNext, ifstream& fin) {
- next = pitchLineNext;
- for (int i = 0; i < 16; i++) //good pitch line
- pitchFunc[i] = (int) i;
- for (int i = 16; i < 32; i++)
- pitchFunc[i] = (int) ((i-16));
- for (int i = 32; i < 48; i++)
- pitchFunc[i] = (int) ((i-32));
- for (int i = 48; i < 56; i++)
- pitchFunc[i] = (int) ((i-32));
- for (int i = 56; i < 64; i++)
- pitchFunc[i] = (int) (80-i);
- }
-
- SyncLine::SyncLine(SyncLine* syncLineNext, PitchLine* corrLine, ifstream& fin) {
- #pragma unused (corrLine)
- next = syncLineNext;
- for(short i = 0; i < 24; ++i)
- syncFunc[i] = 1; //all quarter notes
- for(short i = 24; i < 38; ++i)
- syncFunc[i] = 3;
- for(short i = 38; i < 54; ++i)
- syncFunc[i] = 2; //all dotted eighth notes
- for(short i = 54; i < 64; ++i)
- syncFunc[i] = 1;
- }
-
- Note Unit::PickNote(int measureCount, PitchLine* pl, SyncLine* sl, int beatCount, char random) {
- #pragma unused(random)
- Note endNote;
- short linePitch;
- int measureOfPL = measureCount % 4;
- short rand = (short) random;
- endNote.volume = 0x40;
-
- linePitch = pl->getPitch(measureOfPL*16 + beatCount);
- if (rand > 136) linePitch += 3;
- if (rand < 64) linePitch -= 3;
- if (measureCount != 8) {
- switch (linePitch % 12) {
- case 1:
- endNote.pitch = linePitch - 1;
- break;
- case 2:
- endNote.pitch = linePitch + 1;
- break;
- case 4:
- if (rand < 60)
- endNote.pitch = linePitch - 1;
- else if (rand < 100)
- endNote.pitch = linePitch + 2;
- else
- endNote.pitch = linePitch + 1;
- break;
- case 8:
- endNote.pitch = linePitch - 1;
- break;
- case 9:
- endNote.pitch = linePitch + 1;
- break;
- case 11:
- if (rand < 72)
- endNote.pitch = linePitch - 1;
- else
- endNote.pitch = linePitch + 1;
- break;
- default:
- // case 0: case 3: case 5: case 6: case 7: case 9:
- endNote.pitch = linePitch;
- break;
- }
- }
- else {
- switch (linePitch % 12) {
- case 0:
- endNote.pitch = linePitch - 1;
- break;
- case 1:
- endNote.pitch = linePitch + 1;
- break;
- case 3:
- endNote.pitch = linePitch - 1;
- break;
- case 4:
- endNote.pitch = linePitch + 1;
- break;
- case 6:
- endNote.pitch = linePitch + 1;
- break;
- case 8:
- endNote.pitch = linePitch - 1;
- break;
- case 10:
- endNote.pitch = linePitch - 1;
- break;
- default:
- // case 2: case 5: case 7: case 9: case 11:
- endNote.pitch = linePitch;
- break;
- }
- }
-
- char holder;
-
- if (endNote.pitch == mArray[measureCount].getStackedNote(1).pitch)
- endNote.pitch = -100; //don't repeat notes
-
- if (mArray[measureCount].getStackedNote(1).duration == 1 && mArray[measureCount].getStackedNote(2).duration == 1 && rand > 65) {
- endNote.duration = 1; //continuity of 16ths
- holder = mArray[measureCount].getStackedNote(1).volume;
- holder += 1;
- mArray[measureCount].setStackedNoteV(1,holder);
- endNote.volume = holder;
- } else if (mArray[measureCount].getStackedNote(1).duration == 3) {
- endNote.duration = 1;
- mArray[measureCount].setStackedNoteV(1, 0x4E);
- } else
- endNote.duration = min(sl->getSync(measureOfPL*16 + beatCount), 16 - beatCount);
-
- if ((endNote.duration >= 12-beatCount) && (rand % 3 == 0))
- endNote.pitch = -100;
-
- if (measureCount == 11)
- endNote.pitch = -100;
-
-
- return endNote;
- }